package com.jiangxjsy.gateway.filter;

import com.jiangxjsy.core.constant.GatewayConstant;
import com.jiangxjsy.gateway.service.security.PermissionService;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * wukong-crm-master
 * 蒋胜宇
 * 2025/5/31 14:26
 *
 * <p>
 * 白名单过滤器
 * </p>
 *
 * <p>
 * 如果从前端的请求是定义在白名单中的请求，则直接放行
 * - 扩展 -
 * router.RouteRepository 中已经加载了来自数据库中的路由配置，包括负载均衡
 * 其中配置的路径包含了白名单中请求的路径
 * 例（? => *）：
 *   路由配置中的 admin?/?? 与白名单中的 /adminFile/down/?
 * 所以，如果一个请求属于白名单请求导致其被发行，也会触发网关的负载均衡策略
 * </p>
 *
 * <p>
 * - 注意 -
 * 白名单过滤器，忽略拦截过滤器，鉴权过滤器三个过滤器只会有一个触发放行
 * 一旦有一个触发放行，则后面的过滤器不会触发
 * （通过判断 GatewayConstant.SKIP_SUBSEQUENT_FILTERS 是否有值来决定是否直接跳过过滤器）
 * </p>
 */

@Component
public class WhitelistFilter implements GlobalFilter, Ordered {
    @Resource
    private PermissionService permissionService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getPath().value();

        if (permissionService.isWhitelistedRequest(url)) {
            exchange.getAttributes().put(GatewayConstant.SKIP_SUBSEQUENT_FILTERS, true);
            return chain.filter(exchange);
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 白名单过滤器第 1 执行
        return GatewayConstant.FILTER_HIGHEST_ORDER;
    }
}
